package com.oa.hyperion.core;

import com.oa.hyperion.configuration.ExceptionCodeConfig;
import com.oa.hyperion.exception.http.HttpException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author Liu
 * @date 2022年01月17日 13:19
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private final ExceptionCodeConfig exceptionCodeConfig;

    public GlobalExceptionHandler(ExceptionCodeConfig exceptionCodeConfig) {
        this.exceptionCodeConfig = exceptionCodeConfig;
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    public UnifyResponse handlerException(Exception e, HttpServletRequest req) {
        e.printStackTrace();
        return new UnifyResponse(9999, "服务器异常", getRequestInfo(req));
    }

    @ExceptionHandler(HttpException.class)
    public ResponseEntity<UnifyResponse> handleHttpException(HttpException e,HttpServletRequest req){
        UnifyResponse unifyResponse = new UnifyResponse(e.getCode(), exceptionCodeConfig.getMessage(e.getCode()), getRequestInfo(req));
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpStatus httpStatus = HttpStatus.resolve(e.getHttpStatusCode());
        assert httpStatus != null;
        return new ResponseEntity<>(unifyResponse, httpHeaders, httpStatus);
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    public UnifyResponse handlerBindException(BindException e,HttpServletRequest req){
        return new UnifyResponse(10001, formatErrorMessage(e.getBindingResult().getAllErrors()), getRequestInfo(req));
    }
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    @ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED)
    public UnifyResponse handlerHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest req){
        return new UnifyResponse(10000, "当前访问方法不支持", getRequestInfo(req));
    }

    private String formatErrorMessage(List<ObjectError> errorList) {
        StringBuffer errorMsg = new StringBuffer();
        errorList.forEach(error -> errorMsg.append(error.getDefaultMessage()).append(";"));
        return errorMsg.toString();
    }

    private String getRequestInfo(HttpServletRequest req) {
        return req.getMethod() + " " + req.getRequestURI();
    }
}
